package com.shoulder.core.utils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class JsonUtils {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        //默认情况下ObjectMapper序列化没有属性的空对象时会抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        //默认情况下Jackson要求JSON字符串消息 和 Java类中的字段必须一一相对应，否则反序列解析JSON字符串时会报错
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //当反序列化的JSON串里带有反斜杠时，默认objectMapper反序列化会失败
        objectMapper.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
        //当json字符串里带注释符时，默认情况下解析器不能解析
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        //默认情况下不能识别单引号包住的属性和属性值
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        //是否允许JSON字符串包含非引号控制字符（值小于32的ASCII字符，包含制表符\t、换行符\n和回车\r）
        objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        //开启属性名没有双引号的非标准json字符串
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

        //取消时间的转化格式默认是时间戳,可以取消,同时需要设置要表现的时间格式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

        //LocalDateTime
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);

    }


    /**
     * @param jsonArray   json数组
     * @param elementType 转换的类型
     * @param <T>         泛型
     * @return 集合
     */
    public static <T> List<T> json2List(String jsonArray, Class<T> elementType) {
        try {
            return objectMapper.readValue(jsonArray, new TypeReference<>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将对象转为json字符串
     *
     * @param obj 对象
     * @return json字符串
     */
    public static String obj2Json(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断一个字符串是否是 json
     *
     * @param str 字符串
     * @return bool
     */
    public static boolean isTypeJSON(String str) {
        return isTypeJSONObject(str) || isTypeJSONArray(str);
    }

    /**
     * 判断是否是json
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean isTypeJSONObject(String str) {
        if (null == str) {
            return false;
        }
        return str.trim().startsWith("{") && str.trim().endsWith("}");

    }

    /**
     * 是否是json数组
     *
     * @param str json字符串
     * @return boolean
     */
    public static boolean isTypeJSONArray(String str) {
        if (null == str) {
            return false;
        }
        return str.trim().startsWith("[{") && str.trim().endsWith("}]");
    }

    /**
     * json字符串转为bean对象
     *
     * @param jsonString 字符串
     * @param beanClass  beanClass
     * @param <T>        泛型参数
     * @return bean
     */
    public static <T> T json2Bean(String jsonString, Class<T> beanClass) {
        try {
            return objectMapper.readValue(jsonString, beanClass);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
